#include <iostream>
#include <string>
#include <memory>

// 抽象基类
class Car
{
public:
    virtual void intro() = 0;
    virtual ~Car() {}
};
class Bmw : public Car
{
public:
    void intro()
    {
        std::cout << "宝马-德国品牌-始于1916" << std::endl;
    }
};
class Toyota : public Car
{
public:
    void intro()
    {
        std::cout << "丰田-日本品牌-始于1937" << std::endl;
    }
};
class Ford : public Car
{
public:
    void intro()
    {
        std::cout << "福特-美国品牌-始于1903" << std::endl;
    }
};

class People
{
public:
    virtual void name() = 0;
    virtual ~People() {}
};

class German : public People
{
public:
    virtual void name()
    {
        std::cout << "德国人" << std::endl;
    }
};
class Japanese : public People
{
public:
    virtual void name()
    {
        std::cout << "日本人" << std::endl;
    }
};
class American : public People
{
public:
    virtual void name()
    {
        std::cout << "美国人" << std::endl;
    }
};

// 假设某国人只能买某国生产的车

// 抽象工厂
class AbstractFactory
{
public:
    virtual std::shared_ptr<Car> CreateCar() = 0;
    virtual std::shared_ptr<People> SelectPeople() = 0;

    virtual ~AbstractFactory(){};
};

class BmwFactory : public AbstractFactory
{
public:
    std::shared_ptr<Car> CreateCar()
    {
        return std::make_shared<Bmw>();
    }
    std::shared_ptr<People> SelectPeople()
    {
        return std::make_shared<German>();
    }
};
class ToyotaFactory : public AbstractFactory
{
public:
    std::shared_ptr<Car> CreateCar()
    {
        return std::make_shared<Toyota>();
    }
    std::shared_ptr<People> SelectPeople()
    {
        return std::make_shared<Japanese>();
    }
};
class FordFactory : public AbstractFactory
{
public:
    std::shared_ptr<Car> CreateCar()
    {
        return std::make_shared<Ford>();
    }
    std::shared_ptr<People> SelectPeople()
    {
        return std::make_shared<American>();
    }
};

void ProduceCar(std::shared_ptr<AbstractFactory> factory)
{
    // 创建car对象时，等号两边，都不依赖具体类，而是依赖抽象
    // 将依赖具体类的动作，“驱赶”到当前局部域之外
    std::shared_ptr<Car> car = factory->CreateCar();
    car->intro();

    std::shared_ptr<People> people = factory->SelectPeople();
    people->name();
}

int main()
{
    ProduceCar(std::make_shared<ToyotaFactory>());
    ProduceCar(std::make_shared<FordFactory>());
    ProduceCar(std::make_shared<BmwFactory>());

    return 0;
}